﻿using System;
using Org.BouncyCastle.Bcpg.OpenPgp;
using System.IO;

namespace TorBrowserUpdater
{
    class SignatureVerifier
    {
        /// <summary>
        /// Takes the setup download url and downloads the associated signature file.
        /// </summary>
        /// <param name="setupDownloadUrl"></param>
        /// <param name="sigFilename"> </param>
        public static void DownloadSignatureFile(string setupDownloadUrl, out string sigFilename)
        {
            try
            {
                var downloadLink = setupDownloadUrl + ".asc";
                sigFilename = Path.GetFileName(new Uri(downloadLink).LocalPath);
                Console.WriteLine("Downloading setup file signature {0}...", sigFilename);
                Tools.DownloadFile(downloadLink, sigFilename);
            }
            catch (Exception e)
            {
                throw new TBBUpdaterException("Could not download the signature file, aborting update.", e);
            }
        }

        /// <summary>
        /// Verifies the OpenPgp signature of <paramref name="dataFilename"/>, providing the signature stream and the public key stream
        /// </summary>
        /// <param name="dataFilename"></param>
        /// <param name="sigStream"></param>
        /// <param name="publicKey"></param>
        /// <returns></returns>
        public static bool VerifySignature(string dataFilename, Stream sigStream, Stream publicKey)
        {
            Console.WriteLine("Verifying setup signature...");
            try
            {
                var pgpFactory = new PgpObjectFactory(PgpUtilities.GetDecoderStream(sigStream));
                var sigList = (PgpSignatureList)pgpFactory.NextPgpObject();
                var sig = sigList[0];
                var pubKeyBundle = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(publicKey));
                var pubKey = pubKeyBundle.GetPublicKey(sig.KeyId);

                sig.InitVerify(pubKey);
                sig.Update(File.ReadAllBytes(dataFilename));

                return sig.Verify();
            }
            catch (Exception e)
            {
                throw new TBBUpdaterException(
                    "An error occurred while verifying PGP signature of file " + dataFilename, e);
            }
        }
    }
}
